﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace Pixume.TestUnits
{
    /*
     * Purpose: make texture sheets to reduce number of OpenGL calls
     * 
     * Process: build sheets one row at a time, and add them to a master sheet until the sheet is full
     * keep track of each texture location (which will need to be stored in the texture manager) for simple recall
     * 
     * Requirements: 
     * Texture manager cannot load textures and load into opengl in the same call (stitching would end up making opengl calls
     * a ridiculous number of times swapping large amounts of data into memory)
     * 
     * will need 2 separate calls
     * 
     
     */
    public class TexturePacket
    {
        public TexturePacket()
        {
            Left = 0;
            Top = 0;
            Width = 0;
            Height = 0;
            LeftPercent = 0f;
            TopPercent = 0f;
            RightPercent = 0f;
            BottomPercent = 0f;
        }
        public TexturePacket(int pTextureSheet = 0, int pLeft = 0 , int pTop = 0)
        {
            TextureSheet = pTextureSheet;
            Left = pLeft;
            Top = pTop;
        }

        public int TextureSheet { get; set; }

        //in pixels
        public int Left 
        {
            get
            {
                return Left;
            }
            set
            {
                if (Width > 0)
                {
                    Right = Left + Width;
                }
                Left = value;
            }
        }
        public int Top 
        {
            get
            {
                return Top;
            }
            set
            {
                if (Height > 0)
                {
                    Bottom = Top + Height;
                }
                Top = value;
            }
        }
        public int Bottom
        { 
            get 
            {
                return Bottom;
            }
            set
            {
                if (Height > 0)
                {
                    Top = Bottom - Height;
                }
                Bottom = value;
            }
        }
        public int Right
        {

            get
            {
                return Right;
            }
            set 
            { 
                if (Width > 0) 
                {
                    Left = Right - Width;
                }
                Right = value;
            }
        }
        public int Width
        {
            get
            {
                return Width;
            }
            set
            {
                if (value > 0)
                {
                    Width = value;
                    Right = Left + Width;
                }
                else
                {
                    Width = 0;
                }

            }
        }
        public int Height
        {
            get
            {
                return Height;
            }
            set
            {
                if (value > 0)
                {
                    Height = value;
                    Bottom = Top + Height;
                }
                else
                {
                    Height = 0;
                }
            }
        }

        //percents for UV mapping (stored as decimals i.e. 0.0 - 1.0
        public float LeftPercent 
        { 
            get
            {
                return LeftPercent;
            }
            set
            {
                if (value > 1.0f)
                {
                    LeftPercent = 1.0f;
                }
                else if (value < 0.0f)
                {
                    LeftPercent = 0.0f;
                }
                else
                {
                    LeftPercent = value;
                }
            }
        }
        public float TopPercent 
        {
            get
            {
                return TopPercent;
            }
            set
            {
                if (value > 1.0f)
                {
                    TopPercent = 1.0f;
                }
                else if (value < 0.0f)
                {
                    TopPercent = 0.0f;
                }
                else
                {
                    TopPercent = value;
                }
            }
        }
        public float RightPercent
        {
            get
            {
                return RightPercent;
            }
            set
            {
                if (value > 1.0f)
                {
                    RightPercent = 1.0f;
                }
                else if (value < 0.0f)
                {
                    RightPercent = 0.0f;
                }
                else
                {
                    RightPercent = value;
                }
            }
        }
        public float BottomPercent
        {
            get
            {
                return BottomPercent;
            }
            set
            {
                if (value > 1.0f)
                {
                    BottomPercent = 1.0f;
                }
                else if (value < 0.0f)
                {
                    BottomPercent = 0.0f;
                }
                else
                {
                    BottomPercent = value;
                }
            }
        }
    }


    public static class TextureManager
    {
        private static TexturePacket mLastTexture = new TexturePacket();

        private static Dictionary<string, TexturePacket> mTextureLibrary = new Dictionary<string,TexturePacket>();
        private static List<Bitmap> mTextureSheet = new List<Bitmap>();

        private const int TEX_SHEET_MAX_WIDTH = 3072;
        private const int TEX_SHEET_MAX_HEIGHT = 2048;

        public static void AddTexture(string pName, string pPath)
        {
            if (!System.IO.File.Exists(pPath))
            {
                //! error cannot find texture file
                throw new FileNotFoundException("TextureManager: Unable to find texture [" + pName + "]");
            }
            if (Exists(pName))
            {
                //! error texture exists
                throw new ArgumentException("TextureManager: Texture [" + pName + "] already exists!");
            }

            Bitmap subTexture = new Bitmap(pPath);
            TexturePacket subTexturePacket = new TexturePacket();

            subTexturePacket.Width = subTexture.Width;
            subTexturePacket.Height = subTexture.Height;

            //make sure image is less than max width and height, arent negative values
            //if last texture right + new sub texture width > max width go to new row, set left to 0 and height to top + height (bottom)
            //if max height is reached make new sheet, store there
            //store to texture library
            //store in last texture packet
            subTexturePacket.Left = mLastTexture.Left + mLastTexture.Width; 
            
            //need to check current texture sheet
            

            


        }
        public static void OpenGLLoad()
        {
             
        }
        public static void OpenGLUnload()
        {
            //remove all gl buffers
        }
        public static void RemoveTextures()
        {
            //clear all textures
        }
        public static int TextureHandle()
        {
            //grab specific texture from texture sheet
            throw new NotImplementedException();
        }
        public static bool Exists(string pName)
        {
            if (mTextureLibrary.ContainsKey(pName))
            {
                return true;
            }
            return false;
        }
    }
}
